#include "StandardFuncsFX.fxh"

float4x4 g_matWorldViewProject;
float4 g_vMapSize_XZScale_YScale;
float4 g_vCamLookAtDir;
float4 g_vCamPos;
float4 g_vLightDir;
float4 g_vTimeDirection_Unused_Unused;

texture DiffuseSurface;
sampler MeshDiffuseSurface = sampler_state
{
	Texture = <DiffuseSurface>;
	MagFilter = LINEAR;
	MipFilter = LINEAR;
	MinFilter = LINEAR;
	AddressU = Wrap;
	AddressV = Clamp;
};
texture NormalSurface;
sampler MeshNormalSurface = sampler_state
{
	Texture = <NormalSurface>;
	MagFilter = LINEAR;
	MipFilter = LINEAR;
	MinFilter = LINEAR;
	AddressU = Wrap;
	AddressV = Clamp;
};
texture DiffuseBottom;
sampler MeshDiffuseBottom = sampler_state
{
	Texture = <DiffuseBottom>;
	MagFilter = LINEAR;
	MipFilter = LINEAR;
	MinFilter = LINEAR;
	AddressU = Wrap;
	AddressV = Clamp;
};
texture NormalBottom;
sampler MeshNormalBottom = sampler_state
{
	Texture = <NormalBottom>;
	MagFilter = LINEAR;
	MipFilter = LINEAR;
	MinFilter = LINEAR;
	AddressU = Wrap;
	AddressV = Clamp;
};
texture ColorOverlay;
sampler MeshColorOverlay = sampler_state
{
	Texture = <ColorOverlay>;
	MagFilter = LINEAR;
	MipFilter = LINEAR;
	MinFilter = LINEAR;
	AddressU = Wrap;
	AddressV = Wrap;
};
texture HeightNormal;
sampler MeshHeightNormal = sampler_state
{
	Texture = <HeightNormal>;
	MagFilter = LINEAR;
	MipFilter = LINEAR;
	MinFilter = LINEAR;
	AddressU = Wrap;
	AddressV = Wrap;
};

float3 ComposeSpecular( float3 vColor, float vSpecular ) 
{
	return saturate( vColor + vSpecular );
}

struct VS_INPUT
{
	float3 Position			: POSITION;
	float4 UV_Tangent		: TEXCOORD0;
};

struct VS_OUTPUT
{
	float4 Position			: POSITION;
	float4 TextureUV		: TEXCOORD0;
	float4 WorldUV_Tangent	: TEXCOORD1;
	float4 PrePos_Fade		: TEXCOORD2;
	float2 SecondUV			: TEXCOORD3;
};

VS_OUTPUT RenderSceneVS( VS_INPUT Input )
{
	VS_OUTPUT Output = ( VS_OUTPUT )0;

	Output.PrePos_Fade.xyz = Input.Position.xyz;
	Output.PrePos_Fade.w = saturate( 1.0f - Input.UV_Tangent.x );
	
	// 在摄像机空间移动Z值 避免被地表阻挡
	float4 vTempPos = float4( Input.Position.x * g_vMapSize_XZScale_YScale.z, Input.Position.y, Input.Position.z * g_vMapSize_XZScale_YScale.z, 1.0f );
	float4 vDistortedPos = vTempPos - g_vCamLookAtDir * 0.1f;
	vTempPos = mul( vTempPos, g_matWorldViewProject );
	float fNewZ = dot( vDistortedPos, float4( g_matWorldViewProject[0][2], g_matWorldViewProject[1][2], g_matWorldViewProject[2][2], g_matWorldViewProject[3][2] ));
	Output.Position = float4( vTempPos.xy, fNewZ, vTempPos.w );
	
	Output.TextureUV.xy = Input.UV_Tangent.xy;
	Output.TextureUV.x += g_vTimeDirection_Unused_Unused.x * 1.0f * g_vTimeDirection_Unused_Unused.y;
	Output.TextureUV.y += g_vTimeDirection_Unused_Unused.x * 0.2f;
	Output.TextureUV.x *= 0.05f;
	Output.TextureUV.zw = Input.UV_Tangent.xy;
	Output.TextureUV.z *= 0.05f;

	Output.SecondUV = Input.UV_Tangent.xy;
	Output.SecondUV.x += g_vTimeDirection_Unused_Unused.x * 0.9f * g_vTimeDirection_Unused_Unused.y;
	Output.SecondUV.y -= g_vTimeDirection_Unused_Unused.x * 0.1f;
	Output.SecondUV.x *= 0.05f;

	Output.WorldUV_Tangent.x = Input.Position.x / g_vMapSize_XZScale_YScale.x;
	Output.WorldUV_Tangent.y = ( g_vMapSize_XZScale_YScale.y - Input.Position.z - 1.f ) / g_vMapSize_XZScale_YScale.y;
	Output.WorldUV_Tangent.zw = Input.UV_Tangent.zw;

	return Output;
}

float4 RenderScenePS( VS_OUTPUT Input ) : COLOR0
{
	float4 vWaterSurface = tex2D( MeshDiffuseSurface, Input.TextureUV.xw );
	
	float3 vHeightNormal = normalize( tex2D( MeshHeightNormal, Input.WorldUV_Tangent.xy ).rbg - 0.5f );
	float3 vSurfaceNormal1 = normalize( tex2D( MeshNormalSurface, Input.TextureUV.xy ).rgb - 0.5f );
	float3 vSurfaceNormal2 = normalize( tex2D( MeshNormalSurface, Input.SecondUV ).rgb - 0.5f );
	float3 vSurfaceNormal = normalize( vSurfaceNormal1 + vSurfaceNormal2 );
	vSurfaceNormal.xzy = float3( vSurfaceNormal.x * Input.WorldUV_Tangent.zw + vSurfaceNormal.y * float2( -Input.WorldUV_Tangent.w, Input.WorldUV_Tangent.z ), vSurfaceNormal.z );
	vSurfaceNormal = vHeightNormal.yxz * vSurfaceNormal.x +
					 vHeightNormal.xyz * vSurfaceNormal.y +
					 vHeightNormal.xzy * vSurfaceNormal.z;
	// 高光
	float3 vEyeDir = normalize( Input.PrePos_Fade.xyz - g_vCamPos.xyz );
	float3 H = normalize( -g_vLightDir.xyz - vEyeDir );
	float fSpecRemove = 1.0f - abs( 0.5f - Input.TextureUV.w ) * 2.0f;
	float fSpecWidth = 70.0f;
	float fSpecMultiplier = 0.25f;
	float fSpecular = saturate( pow( saturate( dot( H, vSurfaceNormal ) ), fSpecWidth ) * fSpecMultiplier ) * fSpecRemove;

	// 折射
	float2 vDistort = refract( g_vCamLookAtDir.xyz, vSurfaceNormal, 0.66f ).xz;
	vDistort = vDistort.x * Input.WorldUV_Tangent.zw + vDistort.y * float2( -Input.WorldUV_Tangent.w, Input.WorldUV_Tangent.z );
	float3 vBottom = tex2D( MeshDiffuseBottom, Input.TextureUV.zw + vDistort * 0.05f ).rgb;
	float fBottomAlpha = tex2D( MeshDiffuseBottom, Input.TextureUV.zw ).a;
	vBottom = GetOverlay( vBottom, tex2D( MeshColorOverlay, Input.WorldUV_Tangent.xy ).rgb, 0.5f );

	float3 vBottomNormal = normalize( tex2D( MeshNormalSurface, Input.TextureUV.zw ).rgb - 0.5f );
	vBottomNormal.xzy = float3( vBottomNormal.x * Input.WorldUV_Tangent.zw + vBottomNormal.y * float2( -Input.WorldUV_Tangent.w, Input.WorldUV_Tangent.z ), vBottomNormal.z );
	vBottomNormal = 
		  vHeightNormal.yxz * vBottomNormal.x
		+ vHeightNormal.xyz * vBottomNormal.y
		+ vHeightNormal.xzy * vBottomNormal.z;

	float3 vColor = lerp( vBottom, vWaterSurface.xyz, vWaterSurface.a * 0.8f );
	vColor = CalculateLighting( vColor, vBottomNormal );
	return vWaterSurface;
	return float4( ComposeSpecular( vColor, fSpecular * ( 1.0f - Input.PrePos_Fade.w ) * vWaterSurface.a ), fBottomAlpha * ( 1.0f - Input.PrePos_Fade.w ) );
}

technique RiverColor
{
	pass P0
	{
		AlphaBlendEnable = true;
		SrcBlend = SrcAlpha;
		DestBlend = InvSrcAlpha;
		AlphaTestEnable = false;
		FillMode = Solid;
		VertexShader = compile vs_3_0 RenderSceneVS();
		PixelShader = compile ps_3_0 RenderScenePS();
	}
}